package cz.cvut.manatee.client.concordance;

import java.util.LinkedHashMap;
import java.util.LinkedList;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.Messages.Example;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;

import cz.cvut.manatee.client.Resources;
import cz.cvut.manatee.shared.AttributItem;
import cz.cvut.manatee.shared.CorpusInformations;
import cz.cvut.manatee.shared.concordance.CollectedFilterParameters;
import cz.cvut.manatee.shared.concordance.CollectedParameters;
import cz.cvut.manatee.shared.concordance.CollectedSampleParameters;
import cz.cvut.manatee.shared.concordance.CollectedSearchParameters;
import cz.cvut.manatee.shared.concordance.CollectedSimpleOrCqlParameters;
import cz.cvut.manatee.shared.concordance.CollectedSortParameters;


public class SearchWidget extends Composite {
	private final String KEYWORD_ADD_FILTER = "Přidat filtr";
	private final String KEYWORD_ADD_SORT   = "Přidat řazení";
	private final String KEYWORD_ADD_SAMPLE = "Přidat vzorek";
	private final String KEYWORD_FILTER     = "Filtr";
	private final String KEYWORD_SORT       = "Řažení";
	private final String KEYWORD_SAMPLE     = "Vzorek";
	
	private final int MAX_FILTERS = 5;
	private final int MAX_SORTS   = 3;
	private final int MAX_SAMPLES = 1;
	
	private LinkedList<SearchHandler> searchHandlers;

	private LinkedList<CorpusInformations> corpusesList;
	
	private final ListBox korpusy;
	private final SimpleOrCqlWidget search;
	
	private final Button addFilter;
	private final Button addSort;
	private final Button addSample;
	
	private final SearchWidgetManagement<FilterWidget> filters;
	private final SearchWidgetManagement<SortWidget>   sorts;
	private final SearchWidgetManagement<SampleWidget> samples;
	
	Button vyhledat;
	
	public SearchWidget() {
		super();
		
		searchHandlers = new LinkedList<SearchHandler>();
		
		korpusy = new ListBox(false);
		corpusesList = new LinkedList<CorpusInformations>();
		
		addFilter = new Button(KEYWORD_ADD_FILTER);
		addSort   = new Button(KEYWORD_ADD_SORT);
		addSample = new Button(KEYWORD_ADD_SAMPLE);
		
		filters = new SearchWidgetManagement<FilterWidget>(KEYWORD_FILTER);
		sorts   = new SearchWidgetManagement<SortWidget>(KEYWORD_SORT);
		samples = new SearchWidgetManagement<SampleWidget>(KEYWORD_SAMPLE);
		
		HorizontalPanel searchPanel = new HorizontalPanel();
		searchPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
		search = new SimpleOrCqlWidget();
		search.setStylePrimaryName(Resources.INSTANCE.css().form());
		
		vyhledat = new Button("Vyhledat");
		
		searchPanel.add(korpusy);
		searchPanel.add(search);
		searchPanel.add(vyhledat);
		
		HorizontalPanel buttons = new HorizontalPanel();
		buttons.add(addFilter);
		buttons.add(addSort);
		buttons.add(addSample);
		
		VerticalPanel main = new VerticalPanel();
		main.setStylePrimaryName(Resources.INSTANCE.css().verticalPanel());
		main.add(new HTML("<h1>Konkordance</h1>"));
		main.add(searchPanel);
		main.add(filters.layout());
		main.add(sorts.layout());
		main.add(samples.layout());
		main.add(buttons);
		
		this.initWidget(main);
		
		
		
		
		
		
		
		vyhledat.addClickHandler(
			new ClickHandler() {
				public void onClick(ClickEvent event) {
					boolean status = true;
					status = SearchWidget.this.search.validate()  && status;
					status = SearchWidget.this.filters.validate() && status;
					status = SearchWidget.this.sorts.validate()   && status;
					status = SearchWidget.this.samples.validate() && status;
					
					if (status) {
						SearchWidget.this.fireSearchEvent();
					}
				}
			}
		);
			
		korpusy.addChangeHandler(
			new ChangeHandler() {
				public void onChange(ChangeEvent event) {
					SearchWidget.this.search.setLemmatized( !SearchWidget.this.search.isLemmatized() );
					SearchWidget.this.setAttributs(SearchWidget.this.corpusesList.get(SearchWidget.this.korpusy.getSelectedIndex()).getCorpusAttributs());
				}
			}
		);
		
		addFilter.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				addFilter();
			}
		});
		
		addSort.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				addSort();
			}
		});
		
		addSample.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				addSample();
			}
		});
		
		FormChangeHandler refreshButtonsHandler = new FormChangeHandler() {
			public void onFormChange(FormChangeEvent e) {
				SearchWidget.this.refreshButtons();
			}
		};
		
		filters.addFormChangeHandler(refreshButtonsHandler);
		sorts.addFormChangeHandler(refreshButtonsHandler);
		samples.addFormChangeHandler(refreshButtonsHandler);
	}
	
	public void setCorpusesAndAttributes(CorpusInformations[] corpuses){
		if(corpuses != null){
			this.corpusesList.clear();
			this.korpusy.clear();
			
			for(CorpusInformations corp : corpuses){
				this.corpusesList.add(corp);
				this.korpusy.addItem(corp.getCorpusTitle(), corp.getCorpusName());
			}
			
			korpusy.setSelectedIndex(0);
			setAttributs(corpusesList.get(korpusy.getSelectedIndex()).getCorpusAttributs());
			
			this.korpusy.addChangeHandler(new ChangeHandler(){
				public void onChange(ChangeEvent e){
					SearchWidget.this.setAttributs(SearchWidget.this.corpusesList.get(SearchWidget.this.korpusy.getSelectedIndex()).getCorpusAttributs());
				}
			});
			
		}
	}
	
	private void refreshButtons() {
		if (this.samples.size() >= this.MAX_SAMPLES) {
			addSample.setEnabled(false);
		} else {
			addSample.setEnabled(true);
		}
		
		if (this.sorts.size() >= this.MAX_SORTS) {
			addSort.setEnabled(false);
		} else {
			addSort.setEnabled(true);
		}
		
		if (this.filters.size() >= this.MAX_FILTERS) {
			addFilter.setEnabled(false);
		} else {
			addFilter.setEnabled(true);
		}
	}
	
	
	private void fireSearchEvent() {
		for (SearchHandler handler : this.searchHandlers) {
			handler.onSearch(new SearchEvent());
		}
	}
	
	public void addSearchHandler(SearchHandler handler) {
		this.searchHandlers.add(handler);
	}
	
	private void addFilter(){
		if (SearchWidget.this.filters.size() < SearchWidget.this.MAX_FILTERS) {
			SearchWidget.this.filters.add(new FilterWidget());
			SearchWidget.this.refreshButtons();
			SearchWidget.this.filters.setAttributs(SearchWidget.this.corpusesList.get(SearchWidget.this.korpusy.getSelectedIndex()).getCorpusAttributs());
		}
	}
	
	private void addSort(){
		if (SearchWidget.this.sorts.size() < SearchWidget.this.MAX_SORTS) {
			LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
			for(AttributItem attribute : SearchWidget.this.corpusesList.get(SearchWidget.this.korpusy.getSelectedIndex()).getCorpusAttributs()){
				map.put(attribute.getAttributName(), attribute.getTitle());
			}
			
			LinkedHashMap<String, String> map2 = new LinkedHashMap<String, String>();
			map2.put("3l", "3. v levo");
			map2.put("2l", "2. v levo");
			map2.put("1l", "1. v levo");
			map2.put("kwic", "Kwic");
			map2.put("1r", "1. v pravo");
			map2.put("2r", "2. v pravo");
			map2.put("3r", "3. v pravo");
			
			SearchWidget.this.sorts.add(new SortWidget(map, null, map2, "kwic"));
			SearchWidget.this.refreshButtons();
		}
	}
	
	private void addSample(){
		if (SearchWidget.this.samples.size() < SearchWidget.this.MAX_SAMPLES) {
			SearchWidget.this.samples.add(new SampleWidget());
			SearchWidget.this.refreshButtons();
			SearchWidget.this.filters.setAttributs(SearchWidget.this.corpusesList.get(SearchWidget.this.korpusy.getSelectedIndex()).getCorpusAttributs());
		}
	}
	
	/**
	 * Vyhledat - stejne, jako kliknout na tlacitko vyhledat.
	 */
	public void search() {
		this.vyhledat.click();
	}

	public String getCorpusName(){
		return korpusy.getValue(korpusy.getSelectedIndex());
	}

	protected void setCorpusName(String corpusName){
		if (korpusy.getItemCount() > 0) {
			if(corpusName==null){
				korpusy.setItemSelected(0, true);
				return;
			}
			for (int iter = 0; iter < korpusy.getItemCount(); iter++) {
				if (korpusy.getValue(iter).equals(corpusName)) {
					korpusy.setItemSelected(iter, true);
				}
			}
		}
	}
	
	public void setAttributs(AttributItem[] attributs) {
		search.setAttributes(attributs);
		filters.setAttributs(attributs);
		sorts.setAttributs(attributs);
		samples.setAttributs(attributs);
	}

	public CollectedSearchParameters getParameters() {
		CollectedSearchParameters bla = new CollectedSearchParameters(getCorpusName(), (CollectedSimpleOrCqlParameters)search.getParameters(), (CollectedFilterParameters[])filters.getParameters(), (CollectedSortParameters[])sorts.getParameters(), (CollectedSampleParameters[])samples.getParameters());
		return bla;
	}

	public void setParameters(CollectedSearchParameters params) {
		this.setCorpusName(params.getCorpusName());
		search.setParameters(params.getSimpleOrCqlParameters());
		filters.setParameters(params.getFilters());
		sorts.setParameters(params.getSorts());
		samples.setParameters(params.getSamples());
		
	}

}
